home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / javax / swing / JToolBar.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  18.3 KB  |  667 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)JToolBar.java    1.63 98/08/28
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package javax.swing;
  16.  
  17. import java.awt.Color;
  18. import java.awt.Component;
  19. import java.awt.Dimension;
  20. import java.awt.Graphics;
  21. import java.awt.Insets;
  22. import java.awt.event.*;
  23. import java.beans.*;
  24.  
  25. import javax.swing.border.Border;
  26. import javax.swing.plaf.*;
  27. import javax.accessibility.*;
  28.  
  29. import java.io.Serializable;
  30. import java.io.ObjectOutputStream;
  31. import java.io.ObjectInputStream;
  32. import java.io.IOException;
  33. import java.util.Hashtable;
  34.  
  35.  
  36. /**
  37.  * JToolBar provides a component which is useful for displaying commonly
  38.  * used Actions or controls.  It can be dragged out into a separate window
  39.  * by the user (unless the floatable property is set to false).  In order
  40.  * for drag-out to work correctly, it is recommended that you add JToolBar
  41.  * instances to one of the four 'sides' of a container whose layout manager 
  42.  * is a BorderLayout, and do not add children to any of the other four 'sides'.
  43.  * <p>
  44.  * For the keyboard keys used by this component in the standard Look and
  45.  * Feel (L&F) renditions, see the
  46.  * <a href="doc-files/Key-Index.html#JToolBar">JToolBar</a> key assignments.
  47.  * <p>
  48.  * <strong>Warning:</strong>
  49.  * Serialized objects of this class will not be compatible with
  50.  * future Swing releases.  The current serialization support is appropriate
  51.  * for short term storage or RMI between applications running the same
  52.  * version of Swing.  A future release of Swing will provide support for
  53.  * long term persistence.
  54.  *
  55.  * @version 1.63 08/28/98
  56.  * @author Georges Saab
  57.  * @author Jeff Shapiro
  58.  * @see Action
  59.  */
  60. public class JToolBar extends JComponent implements SwingConstants, Accessible
  61. {
  62.     /**
  63.      * @see #getUIClassID
  64.      * @see #readObject
  65.      */
  66.     private static final String uiClassID = "ToolBarUI";
  67.  
  68.     private    boolean   paintBorder              = true;  
  69.     private    Insets    margin                   = null;
  70.     private    boolean   floatable                = true;
  71.     private    int       orientation              = HORIZONTAL;
  72.  
  73.     /* registry of listeners created for Action-JButton
  74.      * linkage.  This is needed sot that references can
  75.      * be cleaned up at remove time to allow GC.
  76.      */
  77.     private static Hashtable listenerRegistry = null;
  78.  
  79.  
  80.     /**
  81.      * Create a new toolbar.  Orientration defaults to horizontal.
  82.      */
  83.     public JToolBar()
  84.     {
  85.         this( HORIZONTAL );
  86.     }
  87.  
  88.     /**
  89.      * Create a new toolbar.
  90.      * 
  91.      * @param orientation  The initial orientation (HORIZONTAL/VERTICAL)
  92.      */
  93.     public JToolBar( int orientation )
  94.     {
  95.         checkOrientation( orientation );
  96.  
  97.     this.orientation = orientation;
  98.  
  99.     if ( orientation == VERTICAL )
  100.     {
  101.         this.setLayout( new BoxLayout( this, BoxLayout.Y_AXIS ) );
  102.     }
  103.     else
  104.     {
  105.         this.setLayout( new BoxLayout( this, BoxLayout.X_AXIS ) );
  106.     }
  107.  
  108.         updateUI();
  109.     }
  110.  
  111.     /**
  112.      * Returns the toolbar's current UI.
  113.      * @see #setUI
  114.      */
  115.     public ToolBarUI getUI() {
  116.         return (ToolBarUI)ui;
  117.     }
  118.     
  119.     /**
  120.      * Sets the L&F object that renders this component.
  121.      *
  122.      * @param ui  the ToolBarUI L&F object
  123.      * @see UIDefaults#getUI
  124.      * @beaninfo
  125.      * description: The menu item's UI delegate
  126.      *       bound: true
  127.      *      expert: true
  128.      *      hidden: true
  129.      */
  130.     public void setUI(ToolBarUI ui) {
  131.         super.setUI(ui);
  132.     }
  133.     
  134.     /**
  135.      * Notification from the UIFactory that the L&F has changed. 
  136.      * Called to replace the UI with the latest version from the 
  137.      * UIFactory.
  138.      *
  139.      * @see JComponent#updateUI
  140.      */
  141.     public void updateUI() {
  142.         setUI((ToolBarUI)UIManager.getUI(this));
  143.         invalidate();
  144.     }
  145.  
  146.  
  147.  
  148.     /**
  149.      * Returns the name of the L&F class that renders this component.
  150.      *
  151.      * @return "ToolBarUI"
  152.      * @see JComponent#getUIClassID
  153.      * @see UIDefaults#getUI
  154.      */
  155.     public String getUIClassID() {
  156.         return uiClassID;
  157.     }
  158.  
  159.  
  160.     /**
  161.      * Returns the index of the specified component.
  162.      * (Note: Separators occupy index positions.)
  163.      *
  164.      * @param c  the Component to find
  165.      * @return an int indicating the component's position, where 0=first
  166.      */
  167.     public int getComponentIndex(Component c) {
  168.         int ncomponents = this.getComponentCount();
  169.         Component[] component = this.getComponents();
  170.         for (int i = 0 ; i < ncomponents ; i++) {
  171.             Component comp = component[i];
  172.             if (comp == c) 
  173.                 return i;
  174.         }
  175.         return -1;
  176.     }
  177.  
  178.     /**
  179.      * Returns the component at the specified index.
  180.      *
  181.      * @param i  the component's position, where 0=first
  182.      * @return   the Component at that position, or null for an
  183.      *           invalid index
  184.      *
  185.      */
  186.     public Component getComponentAtIndex(int i) {
  187.         int ncomponents = this.getComponentCount();
  188.         if ( i >= 0 && i < ncomponents) {
  189.             Component[] component = this.getComponents();
  190.             return component[i];
  191.         }
  192.         return null;
  193.     }
  194.  
  195.      /**
  196.       * Sets the margin between the toolbar's border and
  197.       * its buttons. Setting to null causes the toolbar to
  198.       * use the default margins. The toolbar's default Border
  199.       * object uses this value to create the proper margin.
  200.       * However, if a non-default border is set on the toolbar, 
  201.       * it is that Border object's responsibility to create the
  202.       * appropriate margin space (otherwise this property will 
  203.       * effectively be ignored).
  204.       *
  205.       * @param m an Insets object that defines the space between the 
  206.       *          border and the buttons
  207.       * @see Insets
  208.       * @beaninfo
  209.       * description: The margin between the toolbar's border and contents
  210.       *       bound: true
  211.       *      expert: true
  212.       */
  213.      public void setMargin(Insets m)
  214.      {
  215.          Insets old = margin;
  216.          margin = m;
  217.          firePropertyChange("margin", old, m);
  218.      revalidate();
  219.      repaint();
  220.      }
  221.  
  222.      /**
  223.       * Returns the margin between the toolbar's border and
  224.       * its buttons.
  225.       *
  226.       * @return an Insets object containing the margin values
  227.       * @see Insets
  228.       */
  229.      public Insets getMargin()
  230.      {
  231.          if(margin == null) {
  232.              return new Insets(0,0,0,0);
  233.          } else {
  234.              return margin;
  235.          }
  236.      }
  237.  
  238.      /**
  239.       * Checks whether the border should be painted.
  240.       *
  241.       * @return true if the border should be painted, else false
  242.       * @see setBorderPainted
  243.       */
  244.      public boolean isBorderPainted()
  245.      {
  246.          return paintBorder;
  247.      }
  248.      
  249.  
  250.      /**
  251.       * Sets whether the border should be painted.
  252.       *
  253.       * @param b if true, the border is painted.
  254.       * @see isBorderPainted
  255.       * @beaninfo
  256.       * description: Does the toolbar paint its borders?
  257.       *       bound: true
  258.       *      expert: true
  259.       */
  260.      public void setBorderPainted(boolean b)
  261.      {
  262.          if ( paintBorder != b )
  263.          {
  264.          boolean old = paintBorder;
  265.          paintBorder = b;
  266.          firePropertyChange("borderpainted", old, b);
  267.          revalidate();
  268.          repaint();
  269.      }
  270.      }
  271.  
  272.      /**
  273.       * Paint the toolbar's border if BorderPainted property is true.
  274.       * 
  275.       * @param g  the Graphics context in which the painting is done
  276.       * @see JComponent#paint
  277.       * @see JComponent#setBorder
  278.       */
  279.      protected void paintBorder(Graphics g)
  280.      {    
  281.          if (isBorderPainted())
  282.      {
  283.              super.paintBorder(g);
  284.          }
  285.      }
  286.  
  287.     /** 
  288.      * Return true if the Toolbar can be dragged out by the user.
  289.      *
  290.      * @return true if the Toolbar can be dragged out by the user
  291.      */
  292.     public boolean isFloatable()
  293.     {
  294.         return floatable;
  295.     }
  296.  
  297.      /**
  298.       * Sets whether the toolbar can be made to float
  299.       *
  300.       * @param b if true, the toolbar can be dragged out
  301.       * @see isFloatable
  302.       * @beaninfo
  303.       * description: Can the toolbar be made to float by the user?
  304.       *       bound: true
  305.       *   preferred: true
  306.       */
  307.     public void setFloatable( boolean b )
  308.     {
  309.         if ( floatable != b )
  310.     {
  311.             boolean old = floatable;
  312.         floatable = b;
  313.  
  314.         firePropertyChange("floatable", old, b);
  315.         revalidate();
  316.         repaint();
  317.         }
  318.     }
  319.  
  320.     /**
  321.      * Returns the current orientation of the toolbar
  322.      *
  323.      * @return an int representing the current orientation (HORIZONTAL/VERTICAL)
  324.      * @see setOrientation
  325.      */
  326.     public int getOrientation()
  327.     {
  328.         return this.orientation;
  329.     }
  330.  
  331.     /**
  332.      * Set the orientation of the toolbar
  333.      *
  334.      * @param o  The new orientation (HORIZONTAL/VERTICAL)
  335.      * @see getOrientation
  336.      * @beaninfo
  337.      * description: The current orientation of the toolbar
  338.      *       bound: true
  339.      *   preferred: true
  340.      */
  341.     public void setOrientation( int o )
  342.     {
  343.         checkOrientation( o );
  344.  
  345.     if ( orientation != o )
  346.     {
  347.         int old = orientation;
  348.         orientation = o;
  349.  
  350.         if ( o == VERTICAL )
  351.             setLayout( new BoxLayout( this, BoxLayout.Y_AXIS ) );
  352.         else
  353.             setLayout( new BoxLayout( this, BoxLayout.X_AXIS ) );
  354.  
  355.         firePropertyChange("orientation", old, o);
  356.         revalidate();
  357.         repaint();
  358.     }
  359.     }
  360.  
  361.  
  362.     private void checkOrientation( int orientation )
  363.     {
  364.         switch ( orientation )
  365.     {
  366.             case VERTICAL:
  367.             case HORIZONTAL:
  368.                 break;
  369.             default:
  370.                 throw new IllegalArgumentException( "orientation must be one of: VERTICAL, HORIZONTAL" );
  371.         }
  372.     }
  373.  
  374.     /**
  375.      * Appends a toolbar separator of default size to the end of the toolbar.
  376.      */
  377.     public void addSeparator()
  378.     {
  379.         JToolBar.Separator s = new JToolBar.Separator();
  380.         add(s);
  381.     }
  382.  
  383.     /**
  384.      * Appends a toolbar separator to the end of the toolbar.
  385.      *
  386.      * @param size the size of the separator
  387.      */
  388.     public void addSeparator( Dimension size )
  389.     {
  390.         JToolBar.Separator s = new JToolBar.Separator( size );
  391.         add(s);
  392.     }
  393.  
  394.     /**
  395.      * Add a new JButton which dispatches the action.
  396.      *
  397.      * @param a the Action object to add as a new menu item
  398.      */
  399.     public JButton add(Action a) {
  400.         JButton b = new JButton((String)a.getValue(Action.NAME),
  401.                                 (Icon)a.getValue(Action.SMALL_ICON));
  402.         b.setHorizontalTextPosition(JButton.CENTER);
  403.         b.setVerticalTextPosition(JButton.BOTTOM);
  404.         b.setEnabled(a.isEnabled());
  405.         b.addActionListener(a);
  406.         add(b);
  407.     PropertyChangeListener actionPropertyChangeListener = 
  408.             createActionChangeListener(b);
  409.     if (listenerRegistry == null) {
  410.         listenerRegistry = new Hashtable();
  411.     }
  412.     listenerRegistry.put(b, actionPropertyChangeListener);
  413.     listenerRegistry.put(actionPropertyChangeListener, a);
  414.     a.addPropertyChangeListener(actionPropertyChangeListener);
  415.         return b;
  416.     }
  417.  
  418.     /**
  419.      * Remove the Component from the tool bar.
  420.      * @param comp the component to be removed.
  421.      */
  422.     public void remove(Component comp) {
  423.     super.remove(comp);
  424.     if (comp instanceof JButton) {
  425.         JButton item = (JButton)comp;
  426.         if (listenerRegistry != null) { 
  427.         ActionChangedListener p = (ActionChangedListener)listenerRegistry.remove(item);
  428.         Action a = (Action)listenerRegistry.remove(p);
  429.         item.removeActionListener(a);
  430.         if (p!=null)
  431.             p.setTarget(null);
  432.         if (a!=null)
  433.             a.removePropertyChangeListener(p);
  434.         }
  435.     }
  436.     }
  437.  
  438.     protected void addImpl(Component comp, Object constraints, int index) {
  439.         super.addImpl(comp, constraints, index);
  440.         if (comp instanceof JButton) {
  441.             ((JButton)comp).setDefaultCapable(false);
  442.         }
  443.     }
  444.  
  445.     protected PropertyChangeListener createActionChangeListener(JButton b) {
  446.         return new ActionChangedListener(b);
  447.     }
  448.  
  449.     private class ActionChangedListener implements PropertyChangeListener {
  450.         JButton button;
  451.         
  452.         ActionChangedListener(JButton b) {
  453.             super();
  454.             setTarget(b);
  455.         }
  456.         public void propertyChange(PropertyChangeEvent e) {
  457.             String propertyName = e.getPropertyName();
  458.             if (e.getPropertyName().equals(Action.NAME)) {
  459.                 String text = (String) e.getNewValue();
  460.                 button.setText(text);
  461.                 button.repaint();
  462.             } else if (propertyName.equals("enabled")) {
  463.                 Boolean enabledState = (Boolean) e.getNewValue();
  464.                 button.setEnabled(enabledState.booleanValue());
  465.                 button.repaint();
  466.             } else if (e.getPropertyName().equals(Action.SMALL_ICON)) {
  467.                 Icon icon = (Icon) e.getNewValue();
  468.                 button.setIcon(icon);
  469.                 button.invalidate();
  470.                 button.repaint();
  471.             } 
  472.         }
  473.     public void setTarget(JButton b) {
  474.         this.button = b;
  475.     }
  476.     }
  477.  
  478.     /**
  479.      * A toolbar-specific separator. An object with dimension but
  480.      * no contents used to divide buttons on a toolbar into groups.
  481.      */
  482.     static public class Separator extends JSeparator
  483.     {
  484.         private Dimension separatorSize;
  485.  
  486.         /** 
  487.          * Create a new toolbar separator with the default size
  488.          * defined by the current look and feel.
  489.      *
  490.          */
  491.         public Separator()
  492.     {
  493.         this( null );  // let the UI define the default size
  494.         }
  495.  
  496.         /** 
  497.          * Create a new toolbar separator with the specified size
  498.      *
  499.          * @param size the new size of the separator
  500.          */
  501.         public Separator( Dimension size )
  502.     {
  503.         super( JSeparator.HORIZONTAL );
  504.             setSeparatorSize(size);
  505.         }
  506.  
  507.         /**
  508.      * Returns the name of the L&F class that renders this component.
  509.      *
  510.      * @return "ToolBarSeparatorUI"
  511.      * @see JComponent#getUIClassID
  512.      * @see UIDefaults#getUI
  513.      */
  514.         public String getUIClassID()
  515.     {
  516.             return "ToolBarSeparatorUI";
  517.     }
  518.  
  519.         /** 
  520.          * Set the size of the separator
  521.          *
  522.          * @param size the new size of the separator
  523.          */
  524.         public void setSeparatorSize( Dimension size )
  525.     {
  526.             if (size != null) {
  527.                 separatorSize = size;
  528.             } else {
  529.                 super.updateUI();
  530.             }
  531.         this.invalidate();
  532.     }
  533.  
  534.         /** 
  535.          * Return the size of the separator
  536.          *
  537.          * @return the Dimension object containing the separator's
  538.          *         size (This is a reference, NOT a copy!)
  539.          */
  540.         public Dimension getSeparatorSize()
  541.     {
  542.         return separatorSize;
  543.     }
  544.  
  545.         /** 
  546.          * Return the minimum size for the separator
  547.          *
  548.          * @return the Dimension object containing the separator's
  549.          *         minimum size
  550.          */
  551.         public Dimension getMinimumSize()
  552.     {
  553.             return getPreferredSize();
  554.         }
  555.  
  556.         /** 
  557.          * Return the maximum size for the separator
  558.          *
  559.          * @return the Dimension object containing the separator's
  560.          *         maximum size
  561.          */
  562.         public Dimension getMaximumSize()
  563.     {
  564.             return getPreferredSize();
  565.         }
  566.  
  567.         /** 
  568.          * Return the preferred size for the separator
  569.          *
  570.          * @return the Dimension object containing the separator's
  571.          *         preferred size
  572.          */
  573.         public Dimension getPreferredSize()
  574.     {
  575.         return separatorSize.getSize();
  576.         }
  577.     }
  578.  
  579.  
  580.     /** 
  581.      * See readObject() and writeObject() in JComponent for more 
  582.      * information about serialization in Swing.
  583.      */
  584.     private void writeObject(ObjectOutputStream s) throws IOException {
  585.         s.defaultWriteObject();
  586.     if ((ui != null) && (getUIClassID().equals(uiClassID))) {
  587.         ui.installUI(this);
  588.     }
  589.     }
  590.  
  591.  
  592.     /**
  593.      * Returns a string representation of this JToolBar. This method 
  594.      * is intended to be used only for debugging purposes, and the 
  595.      * content and format of the returned string may vary between      
  596.      * implementations. The returned string may be empty but may not 
  597.      * be <code>null</code>.
  598.      * <P>
  599.      * Overriding paramString() to provide information about the
  600.      * specific new aspects of the JFC components.
  601.      * 
  602.      * @return  a string representation of this JToolBar.
  603.      */
  604.     protected String paramString() {
  605.         String paintBorderString = (paintBorder ?
  606.                     "true" : "false");
  607.         String marginString = (margin != null ?
  608.                    margin.toString() : "");
  609.         String floatableString = (floatable ?
  610.                   "true" : "false");
  611.         String orientationString = (orientation == HORIZONTAL ?
  612.                                     "HORIZONTAL" : "VERTICAL");
  613.  
  614.         return super.paramString() +
  615.         ",floatable=" + floatableString +
  616.         ",margin=" + marginString +
  617.         ",orientation=" + orientationString +
  618.         ",paintBorder=" + paintBorderString;
  619.     }
  620.  
  621.  
  622. /////////////////
  623. // Accessibility support
  624. ////////////////
  625.  
  626.     /**
  627.      * Get the AccessibleContext associated with this JComponent
  628.      *
  629.      * @return the AccessibleContext of this JComponent
  630.      */
  631.     public AccessibleContext getAccessibleContext() {
  632.         if (accessibleContext == null) {
  633.             accessibleContext = new AccessibleJToolBar();
  634.         }
  635.         return accessibleContext;
  636.     }
  637.  
  638.     /**
  639.      * The class used to obtain the accessible role for this object.
  640.      */
  641.     protected class AccessibleJToolBar extends AccessibleJComponent {
  642.  
  643.         /**
  644.          * Get the state of this object.
  645.          *
  646.          * @return an instance of AccessibleStateSet containing the current 
  647.          * state set of the object
  648.          * @see AccessibleState
  649.          */
  650.         public AccessibleStateSet getAccessibleStateSet() {
  651.             AccessibleStateSet states = SwingUtilities.getAccessibleStateSet(JToolBar.this);
  652.             // FIXME:  [[[WDW - need to add orientation from BoxLayout]]]
  653.             // FIXME:  [[[WDW - need to do SELECTABLE if SelectionModel is added]]]
  654.             return states;
  655.         }
  656.     
  657.         /**
  658.          * Get the role of this object.
  659.          *
  660.          * @return an instance of AccessibleRole describing the role of the object
  661.          */
  662.         public AccessibleRole getAccessibleRole() {
  663.             return AccessibleRole.TOOL_BAR;
  664.         }
  665.     } // inner class AccessibleJToolBar
  666. }
  667.